#pragma once

#include "StatusMachine/StatusMachine.h"

class ClassicBusinessContext;
class Market;
class Dealing;
class RequestTimeout;

namespace ClassicBusinessStatusMachine{
	class Event
	{
	public:
		enum TYPE {NONE,MARKET_EVENT, DEALING_EVENT,STOP_COMMAND, START_COMMAND, EDIT_COMMAND,CLEAR_COMMAND,REQUEST_TIME_OUT_EVENT};
		explicit Event(TYPE type = NONE);
		explicit Event(Market const& market);
		explicit Event(Dealing const& dealing);
		explicit Event(RequestTimeout const& requestTimeout);
		int GetType() const { return m_type; }
		Market const& GetMarket() const { return *(Market*)m_data; }
		Dealing const& GetDealing() const { return *(Dealing*)m_data; }
		RequestTimeout const& GetRequestTimeout() const { return *(RequestTimeout*)m_data; }

	private:
		int m_type;
		char m_data[1024];
	};

	typedef Status<ClassicBusinessContext,Event> StatusT;
	class StatusBase : public StatusT
	{
	public:
		StatusBase(std::string const& name, ClassicBusinessContext& context)
			:StatusT(name,context)
		{

		}
	private:
		virtual void DoBefore();
	};
	typedef ConditionBase<ClassicBusinessContext,Event> ConditionT;
	typedef StatusMachine<ClassicBusinessContext,Event> StatusMachineT;


#define DEFINE_CONDITION(condition_name)						\
	class condition_name : public ConditionT					\
	{															\
	public:														\
	explicit condition_name(ClassicBusinessContext& context)	\
	:ConditionT(context){}										\
	virtual ~condition_name() {}								\
	private:													\
	virtual bool DoCheck(Event const& event);					\
	}

	DEFINE_CONDITION(OpenMarketAndEnoughFundCondition);
	DEFINE_CONDITION(MinorOpenSendFailedCondition);
	DEFINE_CONDITION(MinorOpenFailedOrLostOpenMarketCondition);
	DEFINE_CONDITION(MinorOpenCancellationSendFailedCondition);
	DEFINE_CONDITION(MinorOpenCancallationTotallySuccessCondition);
	DEFINE_CONDITION(MinorOpenPartialSuccessCondition);
	DEFINE_CONDITION(MinorPartialCancellationSendFailedOrNotTotallySuccessCondition);
	DEFINE_CONDITION(PartialCancellationSentAndRemainIsZeroCondition);
	DEFINE_CONDITION(MinorOpenSuccessCondition);
	DEFINE_CONDITION(LostMajorOpenMarketCondition);
	DEFINE_CONDITION(MinorOffsetFailedCondition);
	DEFINE_CONDITION(MinorOffsetSuccessCondition);
	DEFINE_CONDITION(MajorOpenMarketCondition);
	DEFINE_CONDITION(MajorOpenSendFailedAndOpenMarketCondition);
	DEFINE_CONDITION(MajorOpenPartialSuccessCondition);
	DEFINE_CONDITION(MajorPartialCancellationSendFailedOrNotTotallySuccessCondition);
	DEFINE_CONDITION(MajorPartialCancellationSuccessOrMajorOpenSuccessCondition);
	DEFINE_CONDITION(MajorOpenSuccessCondition);
	DEFINE_CONDITION(MajorOpenSendFailedAndLostOpenMarketCondition);
	DEFINE_CONDITION(MajorOpenFailedOrLostOpenMarketCondition);
	DEFINE_CONDITION(MajorOpenCancellationSendFailedAndLostOpenMarketCondition);
	DEFINE_CONDITION(MajorOpenCancellationSuccessAndOpenMarketCondition);
	DEFINE_CONDITION(MajorOpenCancellationSuccessAndLostOpenMarketCondition);
	DEFINE_CONDITION(OffsetMarketCondition);

	DEFINE_CONDITION(MinorOffsetOrderedCondition);
	DEFINE_CONDITION(MinorOffsettedCondition);
	DEFINE_CONDITION(MinorOffsetAllCancelledCondition);

	DEFINE_CONDITION(StopMarketCondition);
	DEFINE_CONDITION(ClearCommandConditon);
	DEFINE_CONDITION(OffsetPartialSuccessCondition);
	DEFINE_CONDITION(OffsetSuccessCondition);
	DEFINE_CONDITION(StopCondition);
	class PositionZeroAndNotExistCancellableOrderCondition : public ConditionT
	{
	public:
		explicit PositionZeroAndNotExistCancellableOrderCondition(ClassicBusinessContext& context, Event::TYPE commandType)
			:ConditionT(context),m_commandType(commandType)
		{
		}
		virtual ~PositionZeroAndNotExistCancellableOrderCondition(){}
	private:
		virtual bool DoCheck(Event const& event);
		Event::TYPE m_commandType;
	};
	DEFINE_CONDITION(EditCondition);
	DEFINE_CONDITION(Edit2StartCondition);

#undef DEFINE_CONDITION

#define DEFINE_STATUS(class_name,name)					\
	class class_name : public StatusBase					\
	{														\
	public:													\
	explicit class_name(ClassicBusinessContext& context)		\
	:StatusBase(name,context){}							\
	virtual ~class_name(){}								\
	private:											\
	virtual void DoExecute(Event const& event);			\
	}

	DEFINE_STATUS(StartStatus,"start");
	DEFINE_STATUS(MinorOpenSentStatus,"minor open sent");
	DEFINE_STATUS(MinorOpenCancellationSentStatus,"minor open cancellation sent");
	DEFINE_STATUS(MinorPartialCancellationSentStatus,"minor partial cancellation sent");
	DEFINE_STATUS(MarketCheckStatus,"market check");
	DEFINE_STATUS(MinorOffsetAllSentStatus,"minor offset all sent");
	DEFINE_STATUS(MajorOpenSentStatus,"major open sent");
	DEFINE_STATUS(MajorPartialCancellationSentStatus, "major partial cancellation sent");
	DEFINE_STATUS(MajorOpenCancellationSentStatus,"major open cancellation sent");
	DEFINE_STATUS(OpenedStatus,"opened");

	DEFINE_STATUS(WaitToOffsetStatus,"wait to offset");
	DEFINE_STATUS(MinorOffsetSentStatus,"minor offset sent");
	DEFINE_STATUS(MinorOffsetCancelSentStatus,"minor offset ordered");
	DEFINE_STATUS(MajorOffsetSentStatus,"major offset sent");

	DEFINE_STATUS(ClearSentStatus,"clear sent");
	DEFINE_STATUS(StopStatus,"stop");
	DEFINE_STATUS(EditableStatus,"editable");
#undef  DEFINE_STATUS

	StatusMachineT* CreateMachine(ClassicBusinessContext& context);
}